﻿
#include "imagetodatatools.h"
#include "ui_imagetodatatools.h"

ImageToDataTools::ImageToDataTools(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::ImageToDataTools)
{
    ui->setupUi(this);
    initUI();
}

ImageToDataTools::~ImageToDataTools()
{
    delete ui;
}

void ImageToDataTools::initUI()
{
    //窗体居中显示
    QDesktopWidget *desktop=QApplication::desktop();
    int width=desktop->width();
    int height=desktop->height();
    //设置窗口将始终显示在其他窗口之上
    setWindowFlags(Qt::WindowStaysOnTopHint);
    this->move((width-this->width())/2,(height-this->height())/2);

    setWindowIcon(QIcon(":/1.ico"));
    setWindowTitle(tr("图片数据转换工具"));
    this->setAcceptDrops(true);                    //设置允许向窗口拖入

    // 定时器更新
    QTimer *updateTimer = new QTimer(this);
    updateTimer->callOnTimeout(this,&ImageToDataTools::ShowTime);
    updateTimer->start(1000);
}

void ImageToDataTools::ShowTime()
{
    QDateTime time=QDateTime::currentDateTime();
    QString s=time.toString("yyyy年MM月dd日 hh时mm分ss秒 dddd");
    ui->labTime->setText(tr("现在是:%1").arg(s));
}

void ImageToDataTools::DelayTime(int s)
{
    QTime t=QTime::currentTime().addMSecs(s);       // addMSecs(s) 将当前时间增加指定的毫秒数s，得到一个目标时间点t
    while(QTime::currentTime()<t){                  /*处理当前线程的事件队列，并等待最多100毫秒来接收新的事件。
                                                    这是为了确保程序的其他部分仍然能够响应用户操作，避免程序卡死。*/
        QCoreApplication::processEvents(QEventLoop::AllEvents,100);
    }
}

//图片转数据
void ImageToDataTools::PicToData(QString fromPic, QString toData, QString myformat)
{
    QImage img(fromPic);
    // 保存图像数据到 QByteArray
    QByteArray ba;
    QBuffer buf(&ba);
    buf.open(QIODevice::WriteOnly);
    img.save(&buf,"JPG");                           //按照JPG解码保存数据
    buf.close();

    QByteArray cc=qCompress(ba,1);                  // 对图像数据进行压缩

    QByteArray hh;
    if (myformat=="Hex")
    {
        hh=cc.toHex();                              //获取十六进制数据
    }
    else
    {
        hh=cc.toBase64();                           //获取Base64数据
    }
    /*
     * 将hh直接写入文件可能会导致文件保存的是二进制数据，而不是文本数据。
     * 由于文件通常存储文本数据，而不是二进制数据，将QByteArray以文本格式写入文件是常见的做法
     */
    QString str(hh);

    QFile file(toData);
    if (file.open(QFile::WriteOnly|QFile::Truncate))
    {
        file.write(str.toLatin1());                 // 字符编码是Latin1可以表示大多数ASCII字符
        file.close();
    }
}

//数据转图片
void ImageToDataTools::DataToPic(QString fromData, QString toPic, QString myformat)
{
    QFile file(fromData);
    if (file.open(QFile::ReadOnly))
    {
        QByteArray read = file.readAll();
        file.close();

        QByteArray rc;
        if (myformat == "Hex")
        {
            QString hexString = QString::fromLatin1(read);          // Latin1编码方式写入文件,读取转换为字符串
            rc = QByteArray::fromHex(hexString.toLatin1());         // 解析十六进制字符串
        }
        else
        {
            rc = QByteArray::fromBase64(read);
        }
        QByteArray rdc = qUncompress(rc);                           // 解压缩，得到解压后的二进制数据

        QImage img;
        img.loadFromData(rdc);
        img.save(toPic);
    }
}



void ImageToDataTools::on_btnBrowseToPic_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("选择图片文件"), "", tr("图片文件(*.jpg;*.gif;*.bmp;*.png;*.jpeg)"));
    if (fileName.isEmpty())                         // 用户取消选择或者没有选择有效的文件
        fileName= "未选择图片";

    ui->pic->setText(fileName);
    // 自动推算txt路径
    QFileInfo fileInfo(fileName);
    QString txtPath(fileName.remove(fileInfo.suffix())+"txt");// 文件的后缀名
    ui->txt->setText(txtPath);
}


void ImageToDataTools::on_btnBrowseToTxt_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("选择文本文件"), "", tr("文本文件(*.txt)"));
    if (fileName.isEmpty())                         // 用户取消选择或者没有选择有效的文件
        fileName= "未选择文本";

    ui->txt->setText(fileName);
    // 自动推算pic路径
    QFileInfo fileInfo(fileName);
    QString picPath(fileName.remove(fileInfo.suffix())+"jpg");// 文件的后缀名
    ui->pic->setText(picPath);

}

// 图片转数据
void ImageToDataTools::on_btnPicToData_clicked()
{
    if (ui->pic->text()==""||ui->pic->text()=="未选择图片")
    {
        QMessageBox::information(this,tr("提示"),tr("请选择图片文件"));
        return;
    }
    if (ui->txt->text()==""||ui->txt->text()=="未选择文本")
    {
        QMessageBox::information(this,tr("提示"),tr("请选择文本文件"));
        return;
    }
    if (ui->rbtn16->isChecked())
    {
        PicToData(ui->pic->text(),ui->txt->text(),"Hex");
    }
    else
    {
        PicToData(ui->pic->text(),ui->txt->text(),"Base64");
    }
    QMessageBox::information(this,tr("提示"),tr("恭喜你！转换完成！"));
}

// 数据转图片
void ImageToDataTools::on_btnDataToPic_clicked()
{
    if (ui->pic->text()==""||ui->pic->text()=="未选择图片")
    {
        QMessageBox::information(this,tr("提示"),tr("请选择图片文件"));
        return;
    }
    if (ui->txt->text()==""||ui->txt->text()=="未选择文本")
    {
        QMessageBox::information(this,tr("提示"),tr("请选择文本文件"));
        return;
    }
    if (ui->rbtn16->isChecked())
    {
        DataToPic(ui->txt->text(),ui->pic->text(),"Hex");
    }
    else
    {
        DataToPic(ui->txt->text(),ui->pic->text(),"Base64");
    }
    QMessageBox::information(this,tr("提示"),tr("恭喜你！转换完成！"));
}

// 选择JPG
void ImageToDataTools::on_btnSelectFile_clicked()
{
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("选择图片文件"), "", tr("图片文件(*.jpg;*.gif;*.bmp;*.png;*.jpeg)"));
    if (!fileNames.isEmpty())                       // 用户选择有效的文件
        ui->listWidget->addItems(fileNames);
    else
        qDebug() << "未选择文件";
}

// 选择TXT
void ImageToDataTools::on_btnSelectTxt_clicked()
{
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("选择文本文件"), "", tr("文本文件(*.txt)"));
    if (!fileNames.isEmpty())// 用户选择有效的文件
        ui->listWidget->addItems(fileNames);
    else
        qDebug() << "未选择文件";
}

// 批量转图片
void ImageToDataTools::on_btnChangeToJpg_clicked()
{
    QListWidgetItem *myitem;
    int count=ui->listWidget->count();
    if (count==0)
    {
        QMessageBox::information(this,tr("提示"),tr("请选择图片文件"));
        return;
    }

    ui->pbar->setValue(0);
    ui->pbar->setMaximum(count);

    for (int i=0;i<count;i++)
    {
        QString timeNow=QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
        QString saveFileName=QCoreApplication::applicationDirPath()+QString("/%1.jpg").arg(timeNow);
        myitem=ui->listWidget->item(i);
        if (ui->rbtn16->isChecked())
        {
            DataToPic(myitem->text(),saveFileName,"Hex");
        }
        else
        {
            DataToPic(myitem->text(),saveFileName,"Base64");
        }
        ui->pbar->setValue(ui->pbar->value()+1);
        this->DelayTime(1000);                      //为了确保命名不冲突和转换完成，延时1秒
    }
    QMessageBox::information(this,tr("提示"),tr("恭喜你！转换完成！"));
}

// 批量转TXT
void ImageToDataTools::on_btnChangeToTxt_clicked()
{
    QListWidgetItem *myitem;
    int count=ui->listWidget->count();
    if (count==0)
    {
        QMessageBox::information(this,tr("提示"),tr("请选择文本文件"));
        return;
    }

    ui->pbar->setValue(0);
    ui->pbar->setMaximum(count);

    for (int i=0;i<count;i++)
    {
        QString timeNow=QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
        QString saveFileName=QCoreApplication::applicationDirPath()+QString("/%1.txt").arg(timeNow);
        qDebug()<<"saveFileName ="<<saveFileName;
        myitem=ui->listWidget->item(i);
        if (ui->rbtn16->isChecked())
        {
            PicToData(myitem->text(),saveFileName,"Hex");
        }
        else
        {
            PicToData(myitem->text(),saveFileName,"Base64");
        }
        ui->pbar->setValue(ui->pbar->value()+1);
        this->DelayTime(1000);                      //为了确保命名不冲突和转换完成，延时1秒
    }
    QMessageBox::information(this,tr("提示"),tr("恭喜你！转换完成！"));
}

// 双击项
void ImageToDataTools::on_listWidget_doubleClicked(const QModelIndex &index)
{
    // 示例：获取双击的项的文本
    QString text = ui->listWidget->item(index.row())->text();
    qDebug() << "双击了：" << text;
                ui->listWidget->clear();
}

// 处理拖动操作进入窗口事件
void ImageToDataTools::dragEnterEvent(QDragEnterEvent *event)
{ // 处理拖动操作进入的逻辑
    if (event->mimeData()->hasUrls())                  //检查拖放事件的数据是否包含 URL
    {
        QList<QUrl> urls = event->mimeData()->urls();
        foreach (const QUrl &url, urls)
        {
            QString fileName = url.toLocalFile();      // 获取文件的本地路径
            QFileInfo fileInfo(fileName);
            // 将文件的后缀名转换为小写
            if (fileInfo.suffix().toLower() == "jpg" ||
                fileInfo.suffix().toLower() == "gif" ||
                fileInfo.suffix().toLower() == "bmp" ||
                fileInfo.suffix().toLower() == "png" ||
                fileInfo.suffix().toLower() == "jpeg")
            {
                event->acceptProposedAction();          // 接受拖放操作
                return;
            }
        }
    }
    event->ignore();                                    //没有找到匹配的图片文件，忽略拖放操作
}

//处理拖放操作完成的事件。当拖动的数据在窗口上释放时，会触发该事件
void ImageToDataTools::dropEvent(QDropEvent *event)
{
    // 处理文件或文件路径的拖放
    QList<QUrl> urls = event->mimeData()->urls();
    foreach (const QUrl& url, urls) {
        QString filePath = url.toLocalFile();
        qDebug() << "拖放文件：" << filePath;
    }
    if (urls.isEmpty())
        return;

    QString filePath=urls.first().toLocalFile();
    ui->pic->setText(filePath);
}

